package com.duqc.tag.service.impl;

import cn.hutool.json.JSONUtil;
import com.duqc.tag.dao.TagRuleMapper;
import com.duqc.tag.entity.*;
import com.duqc.tag.service.TagDataService;
import com.duqc.tag.service.TagRuleService;
import com.duqc.tag.service.impl.strategy.TagDataStrategy;
import com.duqc.tag.service.impl.strategy.TagStrategyFactory;
import com.duqc.util.IntersectionUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName TagRuleServiceImpl
 * @Description TagRuleServiceImpl
 * @Author duqc
 * @Date 2023/2/8
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class TagRuleServiceImpl implements TagRuleService {

    private final TagRuleMapper tagRuleMapper;

    private final TagDataService tagDataService;

    /**
     * 保存规则信息
     *
     * @param tagRule 规则信息
     */
    @Override
    public void add(TagRule tagRule) {
        this.tagRuleMapper.add(tagRule);
    }

    /**
     * 解析标签数据
     * 每次新增前需要删除已经存在的标签信息
     * 如果有点击标签查看量级与饱和度功能，则需要每次单独计算量级与饱和度信息，存放到一张表中
     *
     * @return ResultMsg
     */
    @Override
    public Object data() {
        //todo 只查询一条
        TagRule tagRule = this.tagRuleMapper.getTagRule();
        TagRuleInfo tagRuleInfo = JSONUtil.toBean(JSONUtil.parseObj(tagRule.getTagRule()), TagRuleInfo.class);
        //规则条件
        List<RuleContentList> ruleContentList = tagRuleInfo.getRuleContentList();
        List<List<String>> list = new ArrayList<>();
        ruleContentList.forEach(contentList -> {
            List<ConditionRule> rules = contentList.getRules();
            List<List<String>> conformList = new ArrayList<>();
            //查询符合条件的标签数据
            getTagData(conformList, rules);
            if ("and".equals(contentList.getRelation())) {
                list.add(IntersectionUtil.getIntersection(conformList));
            }
        });
        //排除条件
        FilterRuleContentList filterRuleContentList = tagRuleInfo.getFilterRuleContentList();
        List<ConditionRule> rules = filterRuleContentList.getRules();
        List<List<String>> notConformList = new ArrayList<>();
        getTagData(notConformList, rules);
        List<List<String>> notList = new ArrayList<>();
        if ("and".equals(filterRuleContentList.getRelation())) {
            notList.add(IntersectionUtil.getIntersection(notConformList));
        }

        saveTagData(notList, list, tagRule, tagRuleInfo.getMatchRuleRelation());
        return new ArrayList<>();
    }

    /**
     * 查询符合条件的标签数据
     *
     * @param listInfo      符合条件的数据
     * @param conditionRule 规则信息
     */
    private void getTagData(List<List<String>> listInfo, List<ConditionRule> conditionRule) {
        conditionRule.forEach(info -> {
            TagDataStrategy tagDataStrategy = TagStrategyFactory.getInstance().get(info.getRuleType());
            List<String> tagData = tagDataStrategy.calculationTag(info.getRules(), info.getRelation());
            if (CollectionUtils.isNotEmpty(tagData)) {
                tagData = tagData.stream().distinct().collect(Collectors.toList());
            }
            listInfo.add(tagData);
        });
    }

    /**
     * 保存标签数据
     *
     * @param notList           排除的标签数据
     * @param list              标签数据
     * @param tagRule           标签规则信息
     * @param matchRuleRelation 标签数据关系
     */
    private void saveTagData(List<List<String>> notList, List<List<String>> list, TagRule tagRule, String matchRuleRelation) {
        List<String> intersection = new ArrayList<>();
        //todo or
        if ("and".equals(matchRuleRelation)) {
            intersection = IntersectionUtil.getIntersection(list);
        }
        //todo 排除notList中的数据
        if (CollectionUtils.isEmpty(intersection)) {
            return;
        }
        this.tagDataService.deleteByTagId(tagRule.getTagId());
        this.tagDataService.saveTagData(intersection, tagRule);
    }

}
